package com.vchecker.iobd_checker;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import com.vchecker.iobd_checker.model.CommDefine;
import com.vchecker.iobd_checker.model.CommEvent;
import com.vchecker.iobd_checker.utils.ConvertUtils;
import com.vchecker.iobd_checker.utils.Decrypt;
import com.vchecker.iobd_checker.utils.Upgrad;
import com.vchecker.iobd_checker.utils.Utils;
import com.vchecker.iobd_checker.view.ProgressButton;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by Yipb on 16-3-10.
 */
public class BluetoothHandler {
    private static final String TAG = "BluetoothHandler";
    private static final boolean D = true;
    // 蓝牙当前连接状态
    public static final int BLUETOOTH_STATE_NONE = 0;       // 初始状态
    public static final int BLUETOOTH_STATE_LISTEN = 1;     // 监听接收
    public static final int BLUETOOTH_STATE_CONNECTING = 2; // 正在连接
    public static final int BLUETOOTH_STATE_CONNECTED = 3;  // 已经连接
    public static final int BLUETOOTH_STATE_CONNECT_FAIL = 4;  // 连接失败
    public static final int BLUETOOTH_STATE_CONNECT_DIS = 5;	//连接丢失
    
    // Socket服务名称
    private static final String NAME = "Bluetooth";
    // 蓝牙串口服务 的UUID
    private static final UUID MY_UUID = UUID
            .fromString("00001101-0000-1000-8000-00805F9B34FB");

    // Name for the SDP record when creating server socket
    private static final String NAME_SECURE = "DefineSecure";
    private static final String NAME_INSECURE = "DefineInsecure";
    // Unique UUID for this application
    private static final UUID MY_UUID_SECURE =
            UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    private static final UUID MY_UUID_INSECURE =
            UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
    Context mContext = null;
    Handler mHandler = null;
    private BluetoothAdapter mAdapter = null;
    private static BluetoothSocket mSocket = null;
    private static int mState;
    private BluetoothDevice mDevice = null;
    private ConnectThread mConnectThread = null;
    private ConnectedThread mConnectedThread = null;

    private boolean mIsUpgradFlag = false;  //是否当前设备已经升级过
    private boolean mAlwaysUpgrad = false;  //是否强制升级

    private static String currSN = "";
    private static String currVer = "";

    public class CmdInfo {
        long sendTime = 0;
        long recvTime = 0;
        byte[] recvBuff = new byte[255];
        int recvLen = 0;
    }
    private Map<Integer, CmdInfo> mMapCmd = new HashMap<Integer, CmdInfo>();
    private int mCurrCmdID = 0;
    public int getCurrCmdID() {
        return mCurrCmdID;
    }

    int maxProgress = 100;
    int currProgress = 0;

    public synchronized int getMaxProgress(){
        return maxProgress;
    }
    public synchronized int getCurrProgress(){
        return currProgress;
    }

    private static BluetoothHandler mInstance = new BluetoothHandler();
    public static BluetoothHandler getInstance(){
        return mInstance;
    }
    BluetoothHandler(){
    }
    /**
     * @Title:
     * @Description: 构造函数
     * @param context
     *            UI Activity 的上下文
     */
    public BluetoothHandler(Context context, Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        setState(BLUETOOTH_STATE_NONE);
        mContext = context;
        mHandler = handler;
    }

    /**
     * 设置当前蓝牙连接状态
     *
     * @param state
     *            整型状态值
     */
    private synchronized void setState(int state) {
        if (D)
            Log.d(TAG, "setState() " + mState + " -> " + state);
        mState = state;

        // Give the new state to the Handler so the UI Activity can update
        // mHandler.obtainMessage(Bluetooth.MESSAGE_Define.BLUETOOTH_STATE_CHANGE,
        // state, -1).sendToTarget();
    }

    /**
     * 返回当前蓝牙连接状态.
     */
    public synchronized int getState() {
        return mState;
    }

    /**
     * 返回当前蓝牙连接状态.
     */
    public synchronized BluetoothSocket getSocket() {
        return mSocket;
    }

    /**
     * 启动连接蓝牙设备线程
     *
     * @param device
     *            指定蓝牙设备
     */
    public synchronized void connect(BluetoothDevice device,boolean alwaysUpgrad,boolean isUpgradFlag) {
        if (D)
           Log.d(TAG, "连接到蓝牙设备: " + device);
        stop();

        mDevice = device;
        mAlwaysUpgrad = alwaysUpgrad;
        mIsUpgradFlag = isUpgradFlag;

        // Start the thread to connect with the given device
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();

        setState(BLUETOOTH_STATE_CONNECTING);
    }

    public String getLanStr(String id){
        String ret = id;
        switch(Integer.valueOf(id)){
            case 0:
                ret = "简体中文";
                break;
            case 1:
                ret =  "繁体中文";
                break;
            case 2:
                ret =  "英文";
                break;
        }
        return ret;
    }
    /**
     * 连接成功，设置状态
     *
     * @param socket
     *            监听串口
     * @param device
     *            连接到的蓝牙设备
     */
    public synchronized void connected(BluetoothSocket socket,
                                       BluetoothDevice device) {
        if (D)
            Log.d(TAG, "connected");
        stop();

        mSocket = socket;

		// Start the thread to manage the connection and perform transmissions
		mConnectedThread = new ConnectedThread(socket);
		mConnectedThread.start();

        String strTemp = "";
        byte[] bufSendData = new byte[]{};
        byte[] bufRecvCmd = new byte[255];

        Bundle data = new Bundle();
        /*查询固件序列号信息
        * 55 AA 01 81 6C 00 02 11 06
        * 55 AA 81 01 D7 00 0F 11 06 42 33 34 31 33 32 36 33 30 30 30 31 31
        * B341326300011
        * */
        Log.i(TAG,"发送命令[获取序列号]");
        int iRet = SendRecvCmd(0x1106,bufSendData,bufRecvCmd,5*1000);
        if(iRet >= 0){
            currSN= new String(bufRecvCmd).trim();
            strTemp = "序列号:"+currSN;
            CommDefine.addLog(TAG,strTemp);
            data.putString("SN",currSN);
            if(!currSN.substring(0,4).equals(MainActivity.currVerInfo.name)){
                CommDefine.addLog(TAG,"版本不匹配:" + currSN.substring(0,4) + " => " + MainActivity.currVerInfo.name);

                mHandler.sendMessage(new CommEvent(
                        CommDefine.MESSAGE_UPGRAD,
                        CommDefine.MESSAGE_UPGRAD_ERR_VER,
                        data).getMsg());
                return ;
            }

            if(!currSN.substring(5,6).equals(MainActivity.currVerInfo.lanId)){
                CommDefine.addLog(TAG,"语言[" + getLanStr(currSN.substring(5,6)) + "]不能升级到[" +
                        getLanStr(MainActivity.currVerInfo.lanId+"")+"]");

                mHandler.sendMessage(new CommEvent(
                        CommDefine.MESSAGE_UPGRAD,
                        CommDefine.MESSAGE_UPGRAD_ERR_LAN,data).getMsg());
                return;
            }

            //CommDefine.addLog(TAG,"当前设备: " + currSN.substring(0,4)  + " 语言: " + currSN.substring(5,6));

        } else {
            CommDefine.addLog(TAG,"发送命令[获取序列号]失败");

            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_ERR_CMD).getMsg());
            return;
        }

        /*查询固件软件版本信息
        * 55 AA 01 81 6C 00 02 10 01
        * 55 AA 81 01 BC 00 0F 10 01 20 20 20 20 42 33 34 31 20 56 33 2E 35
        * B341 V3.5 */
        Log.i(TAG,"发送命令[获取版本]");
        iRet = SendRecvCmd(0x1001,bufSendData,bufRecvCmd,5*1000);
        if(iRet >= 0 || iRet == CommDefine.CMD_REJECT){    //-2:否定应答，无版本号
            currSN = "0";
            float fCurrVer = 0 ;
            if(iRet >= 0) {
                currVer = new String(bufRecvCmd).trim();
                fCurrVer = Float.valueOf(currVer.substring(currVer.length() - 3, currVer.length()));
                data.putFloat("Ver",fCurrVer);
            }
            strTemp = "当前版本:" + currVer;
            if(fCurrVer < MainActivity.currVerInfo.maxMcuVer){
                CommDefine.addLog(TAG, strTemp+ " 升级到 " + MainActivity.currVerInfo.maxMcuVer);
            } else {
                if(mAlwaysUpgrad && !mIsUpgradFlag){
                    CommDefine.addLog(TAG,strTemp + " 强制进行升级到 " + MainActivity.currVerInfo.maxMcuVer);
                } else{

                    CommDefine.addLog(TAG,strTemp + " 为最新版本，不需要升级。 ");

                    if(mIsUpgradFlag) {
                        CommDefine.addLog(TAG,"本机升级过的设备，进入烤机模式.");
                        sendTestCmd();
                    }
                    mHandler.sendMessage(new CommEvent(
                            CommDefine.MESSAGE_UPGRAD,
                            CommDefine.MESSAGE_UPGRAD_NO_NEW,data).getMsg());
                    return;
                }
            }
        } else {
            CommDefine.addLog(TAG,"发送命令[获取版本]失败");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_ERR_CMD,data).getMsg());
            return;
        }

        UpgradTask upgradTask = new UpgradTask(mContext);
        upgradTask.execute();

//        /*进入烤机模式指令
//        *55 AA 01 81 6C 00 02 11 0A */
//        Log.i(TAG,"发送命令[进入烤机模式指令]");
//        iRet = sendRecvCmd(0x110a,bufSendData,bufRecvCmd,5*1000);
//        if(iRet >= 0){
//            Log.i(TAG,"发送命令成功:"+iRet);
//            MainActivity.saveToDB(device.getAddress());
//        }

//        Bundle bundle = new Bundle();
//        bundle.putString("BLUETOOTH_ADDRESS", device.getName());
//        EventBus.getDefault().post(new CommEvent(MESSAGE_BLUETOOTH_STATE_CHANGE, BLUETOOTH_STATE_CONNECTED,bundle));
//        setState(BLUETOOTH_STATE_CONNECTED);
    }

    public void sendTestCmd(){
        byte[] bufRecvCmd = new byte[255];
         /*进入烤机模式指令
            *55 AA 01 81 6C 00 02 11 0A */
        Log.i(TAG,"发送命令[进入烤机模式指令]");
        int iRet = SendRecvCmd(0x110a, new byte[0],bufRecvCmd,5*1000);
        if(iRet >= 0){
            Log.i(TAG,"发送命令成功:"+iRet);
        }
    }

    /**
      * 发送并接收一条命令
      * @author Yipb
      * @time 16-3-12 下午3:55
      */
    public int SendRecvCmd(final int cmdID,final byte[] bufSendData,byte[] bufRecvData) {
        return SendRecvCmd(cmdID,bufSendData,bufRecvData,5*1000);
    }

    public int SendRecvCmd(final int cmdID,final byte[] bufSendData,byte[] bufRecvData,int overtime) {
        Send(cmdID,bufSendData);

        //清空接收
        Arrays.fill(bufRecvData, (byte) 0);
        while (true) {
            //超时判断
            long now = System.currentTimeMillis();
            long begin = mMapCmd.get(cmdID).sendTime;
            if((now - begin) > overtime)
                return CommDefine.CMD_OVERTIME;
            if( mMapCmd.get(cmdID).recvLen >= 9){
                //处理有效数据段
                System.arraycopy(mMapCmd.get(cmdID).recvBuff, 9, bufRecvData, 0, mMapCmd.get(cmdID).recvLen - 9);

                if(cmdID != 0x1F13 && cmdID != 0x1F08 )
                    Log.i(TAG,
                        "<-"
                                + ConvertUtils.bytes2HexString(mMapCmd.get(cmdID).recvBuff,
                                mMapCmd.get(cmdID).recvLen));
                //否定应答判断
                if((mMapCmd.get(cmdID).recvBuff[7]&0xff)*0x100 + (mMapCmd.get(cmdID).recvBuff[8]&0xff) ==0x7F00)
                    return CommDefine.CMD_REJECT;
                return mMapCmd.get(cmdID).recvLen;
            }

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }


    }

    /**
     * 往蓝牙设备发送字节数据 cmdID 发送命令ID bufData 命令带参数数据
     */
    public boolean Send(int cmdID, byte[] bufData) {
        mCurrCmdID = cmdID;

        if (!mMapCmd.containsKey(cmdID)) {
            CmdInfo ci = new CmdInfo();
            mMapCmd.put(cmdID, ci);
        }
        mMapCmd.get(cmdID).sendTime = System.currentTimeMillis();
        mMapCmd.get(cmdID).recvTime = mMapCmd.get(cmdID).sendTime;
        mMapCmd.get(cmdID).recvLen = 0;

        int iCheck = Utils.calcCheckBit(cmdID, 2 + bufData.length, bufData,
                bufData.length);
        int iSendLen = 9 + bufData.length;
        byte[] bufCmd = { 0x55, (byte) 0xAA, 0x01, (byte) 0x81, (byte) iCheck,
                (byte) ((iSendLen - 7)/0x100), (byte) ((iSendLen - 7)%0x100), (byte) (cmdID / 0x100),
                (byte) (cmdID % 0x100) };
        byte[] send = new byte[iSendLen];
        System.arraycopy(bufCmd, 0, send, 0, 9);
        System.arraycopy(bufData, 0, send, 9, bufData.length);

        try {
            if(cmdID != 0x1F13 && cmdID != 0x1F08 )
                Log.i(TAG,
                    "->"
                            + ConvertUtils.bytes2HexString(send,send.length));
            mSocket.getOutputStream().write(send);
        } catch (Exception e) {
            Log.e(TAG, "Exception during write", e);
            return false;
        }
        return true;
    }


    /**
     * 停止所有线程
     */
    public synchronized void stop() {
        Log.d(TAG, "停止所有线程");
        try {
            // Cancel the thread that completed the connection
            if (mConnectThread != null) {
                mConnectThread.cancel();
                mConnectThread = null;
            }

            // Cancel any thread currently running a connection
            if (mConnectedThread != null) {
                mConnectedThread.cancel();
                mConnectedThread = null;
            }
            mSocket.close();
        } catch (Exception e) {
            // TODO: handle exception
            Log.i(TAG, e.toString());
        }
        setState(BLUETOOTH_STATE_NONE);

        //MainActivity.connectFinish();

    }
    
    
    /**
     * @ClassName: ConnectThread
     * @Description: TODO(连接到一个蓝牙设备，)
     * @author Yipb
     * @date 2014年6月21日 下午4:15:12
     *
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            mmDevice = device;
            BluetoothSocket tmp = null;

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                //tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
                tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);	//此方法需sdk2.3以上才有

//				Method m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class });
//				tmp = (BluetoothSocket) m.invoke(device, 1);
            } catch (Exception e) {
                Log.e(TAG, "create() failed", e);
            }
            mmSocket = tmp;
        }

        public void run() {
            Log.i(TAG, "开始 连接蓝牙线程");
            setName("ConnectThread");

//			// Always cancel discovery because it will slow down a connection
            if (mAdapter != null && mAdapter.isDiscovering()) {
                mAdapter.cancelDiscovery();
            }

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mmSocket.connect();
            } catch (Exception e) {
                Log.e(TAG,"unable to connect() socket", e);
                connectionFailed();
                // Close the socket
                try {
                    mmSocket.close();
                } catch (Exception e2) {
                    Log.e(TAG,
                            "unable to close() socket during connection failure",
                            e2);
                }
//				// Start the service over to restart listening mode
//				BluetoothHandler.this.start();
                return;
            }

            // Reset the ConnectThread because we're done
            synchronized (BluetoothHandler.this) {
                mConnectThread = null;
            }

            // Start the connected thread
            connected(mmSocket, mmDevice);
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (Exception e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }



    /**
     * 连接蓝牙失败
     */
    private void connectionFailed() {
        setState(BLUETOOTH_STATE_LISTEN);
        if (D)
            Log.d(TAG, "不能连接到蓝牙设备!");

        CommDefine.addLog(TAG,"不能连接到蓝牙设备!");
        mHandler.sendMessage(new CommEvent(
                CommDefine.MESSAGE_UPGRAD,
                CommDefine.MESSAGE_UPGRAD_CONNECT_FAIL).getMsg());
       // EventBus.getDefault().post(new CommEvent(MESSAGE_BLUETOOTH_STATE_CHANGE, BLUETOOTH_STATE_CONNECT_FAIL));
    }

    /**
     * 蓝牙连接丢失
     */
    public void connectionLost() {
        setState(BLUETOOTH_STATE_LISTEN);
        if (D)
            Log.d(TAG, "蓝牙设备丢失!");


    }

    /**
     * 蓝牙数据超时!
     */
    private void connectionOvertime() {
        Log.i(TAG, "蓝牙数据超时");
    }



    /**
     * @ClassName: ConnectedThread
     * @Description: TODO(监听已经连接蓝牙的通讯)
     * @author Yipb
     * @date 2014年6月21日 下午4:16:10
     *
     */
    long mLastRecvTime = System.currentTimeMillis();
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private boolean isExit = false;
        public ConnectedThread(BluetoothSocket socket) {
            Log.d(TAG, "监听 蓝牙通讯");
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (Exception e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            int iRecvcurrProgress = 0;
            int iDataLen = 0;
            int iRealRecvcurrProgress = 0;

            byte[]  bufReadData = new byte[1];
            byte[]  bufHeadData = new byte[4];
            byte[]  bufAllData = new byte[255];
            while (!isExit) {
                try{
                    //读命令帧头
                    while(true){
                        iRealRecvcurrProgress = mmInStream.read(bufReadData, 0, 1);
                        if(iRealRecvcurrProgress != 1){
                            //L.i(TAG, "iRealRecvcurrProgress = " + iRealRecvcurrProgress);
                            continue;
                        }

                        bufHeadData[0] = bufHeadData[1];
                        bufHeadData[1] = bufHeadData[2];
                        bufHeadData[2] = bufHeadData[3];
                        bufHeadData[3] = bufReadData[0];

                        if ((bufHeadData[0] & 0xFF) == 0x55 && (bufHeadData[1] & 0xFF) == 0xAA
                                && (bufHeadData[2] & 0xFF) == 0x81 && (bufHeadData[3] & 0xFF) == 0x01) {
                            iRecvcurrProgress = 4;
                            System.arraycopy(bufHeadData, 0, bufAllData, 0, 4);
                            break;
                        }
                    }

                    //如果读数据帧失败，直接返回超时
                    while(true)
                    {
                        iRealRecvcurrProgress = mmInStream.read(bufReadData, 0, 1);
                        if(iRealRecvcurrProgress != 1){
                            //L.i(TAG, "iRealRecvcurrProgress = " + iRealRecvcurrProgress);
                            continue;
                        }

                        System.arraycopy(bufReadData, 0, bufAllData, iRecvcurrProgress, 1);
                        iRecvcurrProgress++;

                        //计算数据帧长度
                        if(iRecvcurrProgress == 7){
                            iDataLen = bufAllData[5] * 0x100 + bufAllData[6];
                        }

                        //读取完成退出循环
                        if (iRecvcurrProgress == 7+iDataLen)
                            break;
                    }

//                    Log.i(TAG,
//                            "Recv<-"
//                                    + ConvertUtils.bytes2HexString(bufAllData,
//                                    7 + iDataLen));
                    int currID = (bufAllData[7] & 0xff) * 0x100 + (bufAllData[8] & 0xff);
                    if(currID == 0x7f00)
                        currID = (bufAllData[9] & 0xff) * 0x100 + (bufAllData[10] & 0xff);

                    // 更新命令接收时间
                    CmdInfo ci = null;
                    if (mMapCmd.containsKey(currID)) {
                        ci = mMapCmd.get(currID);
                    }else{
                        ci = new CmdInfo();
                        ci.sendTime = 0;
                    }
                    ci.recvLen = 7 + iDataLen;
                    System.arraycopy(bufAllData, 0, ci.recvBuff, 0, ci.recvLen);
                    ci.recvTime = System.currentTimeMillis();
                    mMapCmd.put(currID, ci);

                    mLastRecvTime = System.currentTimeMillis();

                } catch (Exception e) {
                    Log.e(TAG, "Exception during read", e);
                    return;
                }
            }
        }

        /**
         * Write to the connected OutStream.
         *
         * @param buffer
         *            The bytes to write
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
            } catch (Exception e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            try {
                isExit = true;

                if (mmInStream != null) {
                    mmInStream.close();
                }
                if (mmOutStream != null) {
                    mmOutStream.close();
                }
                mmSocket.close();

                if (mAdapter != null && mAdapter.isDiscovering()) {
                    mAdapter.cancelDiscovery();
                }
                if (mmSocket != null) {
                    mmSocket.close();
                }
            } catch (Exception e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }

    }




    class UpgradTask extends AsyncTask<Void, Integer, Integer> {
        private Context context;
        byte[] dataBuff = new byte[4];
        byte[] recvBuff = new byte[255];
        int recvLen = 0;

        UpgradTask(Context context) {
            this.context = context;
        }

        /**
         * 运行在UI线程中，在调用doInBackground()之前执行
         */
        @Override
        protected void onPreExecute() {
            currProgress = 0;
        }

        /**
         * 后台运行的方法，可以运行非UI线程，可以执行耗时的方法
         */
        @Override
        protected Integer doInBackground(Void... params) {
            String strTemp="";
            String strText="";
            byte[] mcuBuff = Upgrad.getByteArrayFromFile(MainActivity.currVerInfo.maxMcuVerFile);
            byte[] flashBuff = null;
            byte[] tempBuff = null;
            long dwSize = mcuBuff.length;	//总长度
            //起始地址
            System.arraycopy(mcuBuff, (int) (dwSize-8), dataBuff, 0, 4);
            long dwStartAddr = (dataBuff[0]&0xff)*0x1000000+(dataBuff[1]&0xff)*0x10000+(dataBuff[2]&0xff)*0x100+(dataBuff[3]&0xff);
            //起始地址效验
            System.arraycopy(mcuBuff, (int) (dwSize-4), dataBuff, 0, 4);
            long dwStartAddrCheck = (dataBuff[0]&0xff)*0x1000000+(dataBuff[1]&0xff)*0x10000+(dataBuff[2]&0xff)*0x100+(dataBuff[3]&0xff);
            if (~dwStartAddr != dwStartAddrCheck)
            {
                Log.i(TAG,"失败：不是有效的升级文件包");
                return 1;
            }

            maxProgress = (int) (dwSize/256+15);
            flashBuff = Upgrad.getByteArrayFromFile(MainActivity.currVerInfo.maxBinVerFile);
            maxProgress = maxProgress + flashBuff.length/256;
            currProgress=0;

            //MainActivity.startUpgrad();
            Bundle data = new Bundle();
            data.putString("SN",currSN);
            data.putString("Ver",currVer);
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_START,maxProgress,data).getMsg());

            Log.i(TAG,"["+System.currentTimeMillis() + "]正在升级,请稍侯...");
            // 0x1008 复位诊断模块，系统进入引导程序（升级）
            recvLen = SendRecvCmd(0x1008, new byte[0], recvBuff);
            if( recvLen < 0 ){
                Log.i(TAG,"01,错误：复位诊断模块，系统进入引导程序");
                return 1;
            }
            Log.i(TAG,"01,成功：复位诊断模块，系统进入引导程序（升级）");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());
            ;

            // 0x1F02 读IAP版本号，判断版本号与MCU文件的前两个字节是否一致
            recvLen = SendRecvCmd(0x1F02, new byte[0], recvBuff) - 9;
            if(recvLen < 0 ){
                Log.i(TAG,"02,错误：读IAP版本号");
                return 1;
            }
            tempBuff = new byte[recvLen];
            System.arraycopy(recvBuff, 0, tempBuff, 0, recvLen);
            strText = new String(tempBuff);
            Log.i(TAG,"02,成功：读IAP版本号="+strText);
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1F0A 读取厂家信息，判断是否以“V-Checker”开头
            recvLen = SendRecvCmd(0x1F0A, new byte[0], recvBuff) - 9;
            if(recvLen < 0 ){
                Log.i(TAG,"03,错误：读厂家信息");
                return 1;
            }
            tempBuff = new byte[recvLen];
            System.arraycopy(recvBuff, 0, tempBuff, 0, recvLen);
            strText = new String(tempBuff);
            Log.i(TAG,"03,成功：读厂家信息="+strText);
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1F04 申请四个随机数进行身份验证
            recvLen = SendRecvCmd(0x1F04, new byte[0], recvBuff) - 9;
            if(recvLen < 0 ){
                Log.i(TAG,"04,错误：申请身份验证");
                return 1;
            }
            tempBuff = new byte[recvLen];
            System.arraycopy(recvBuff, 0, tempBuff, 0, recvLen);
            strText = ConvertUtils.bytes2HexString(tempBuff,recvLen);
            Log.i(TAG,"04,成功：申请身份验证="+strText);
            //加密字符串
            byte[] decBuff = new byte[recvLen];
            Decrypt.Encrypt_4Byte_To_4Byte_Production(tempBuff, decBuff);
            strText = ConvertUtils.bytes2HexString(decBuff,recvLen);
            Log.i(TAG,"04,成功：加密字符串="+strText);
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1F05 身份验证
            recvLen = SendRecvCmd(0x1F05, decBuff, recvBuff) - 9;
            if(recvLen < 0 ){
                Log.i(TAG,"05,错误：身份验证");
                return 1;
            }
            Log.i(TAG,"05,成功：身份验证");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1005 状态效验 判断生产模式已经身份验证
            recvLen = SendRecvCmd(0x1005, new byte[0], recvBuff) - 9;
            if(recvLen < 0 ){
                Log.i(TAG,"06,错误：状态效验");
                return 1;
            }
            if (recvBuff[0] != 3){
                Log.i(TAG,"06,错误：状态效验  " + (recvBuff[0]&0xff) + " != 3");
                return 1;
            }
            Log.i(TAG,"06,成功：状态效验");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1F0E 对ECU进行编程前的准备工作，解除闪存锁，解除写保护
            recvLen = SendRecvCmd(0x1F0E, new byte[0], recvBuff);
            if(recvLen < 0 ){
                Log.i(TAG,"07,错误：ECU解锁");
                return 1;
            }
            Log.i(TAG,"07,成功：ECU解锁");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            //  0x1F0D 擦除MCU的应用程序空间所有数据
            recvLen = SendRecvCmd(0x1F0D, new byte[0], recvBuff);
            if(recvLen < 0 ){
                Log.i(TAG,"08,错误：擦除MCU的数据");
                return 1;
            }
            Log.i(TAG,"08,成功：擦除MCU的数据");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1F08 对ECU进行编程，根据MCU地址、数据长度、有效数据、写入下位机的ECU
            // 将 升级 文件读取到内存
            Log.i(TAG,"正在对ECU进行编程,请稍候...");

            strText = "";
            dwSize = dwSize - 8;	//最后8个字节为文件效验
            int dwDataLen = 0;
            long dwStartAddrPos = dwStartAddr;
            byte[] bufRead = null;
            boolean isFailed = false;
            for (int i=0;i<=dwSize/256;i++,dwStartAddrPos+=256)					//分组写ECU,数据长度必须是4的倍数
            {
                bufRead = new byte[262];
                //ECU地址
                bufRead[0] = (byte) (dwStartAddrPos/0x1000000);
                bufRead[1] = (byte) (dwStartAddrPos/0x10000);
                bufRead[2] = (byte) (dwStartAddrPos/0x100);
                bufRead[3] = (byte) (dwStartAddrPos%0x100);

                //数据长度
                if (i==dwSize/256)
                    dwDataLen = (int) (dwSize%256);
                else
                    dwDataLen = 256;

                if (dwDataLen == 0)
                    continue;

                bufRead[4] = (byte) (dwDataLen/0x100);
                bufRead[5] = (byte) (dwDataLen%0x100);

                //有效数据
                System.arraycopy(mcuBuff, (int)(dwStartAddrPos - dwStartAddr), bufRead, 6, dwDataLen);

                recvLen = SendRecvCmd(0x1F08,bufRead, recvBuff,10*1000);
                if (recvLen < 0)
                {
                    Log.i(TAG,"错误：对ECU进行编程");
                    isFailed = true;
                    break;
                }

                strTemp = String.format("09-%03d/%d,",i,dwSize/256);
                //Log.i(TAG,strTemp + "成功：对ECU进行编程");
                mHandler.sendMessage(new CommEvent(
                        CommDefine.MESSAGE_UPGRAD,
                        CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());
            }
            if(isFailed){
                return 1;
            }

            Log.i(TAG,"09,成功：对ECU进行编程");

            // 0x1F12 编程MCU完成，生成编程结束标志
            recvLen = SendRecvCmd(0x1F12, new byte[0], recvBuff);
            if(recvLen < 0 ){
                Log.i(TAG,"10,错误：编程MCU完成");
                return 1;
            }
            Log.i(TAG,"10,成功：编程MCU完成");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            // 0x1F0F 锁定MCU存储器
            recvLen = SendRecvCmd(0x1F0F, new byte[0], recvBuff);
            if(recvLen < 0 ){
                Log.i(TAG,"11,错误：锁定MCU存储器");
                return 1;
            }
            Log.i(TAG,"11,成功：锁定MCU存储器");

            Log.i(TAG,"正在对Flash进行编程,请稍候...");
            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

                dwSize = flashBuff.length;
                dwStartAddrPos = 0;
                for (int i=0;i<=dwSize/256;i++,dwStartAddrPos+=256)					//分组写flash
                {
                    bufRead = new byte[262];
                    //数据长度
                    if (i==dwSize/256)
                        dwDataLen = (int) (dwSize%256);
                    else
                        dwDataLen = 256;

                    if (dwDataLen == 0)
                        continue;

                    //地址
                    bufRead[0] = (byte) (dwStartAddrPos/0x1000000);
                    bufRead[1] = (byte) (dwStartAddrPos/0x10000);
                    bufRead[2] = (byte) (dwStartAddrPos/0x100);
                    bufRead[3] = (byte) (dwStartAddrPos%0x100);
                    //长度
                    bufRead[4] = (byte) (dwDataLen/0x100);
                    bufRead[5] = (byte) (dwDataLen%0x100);

                    //有效数据
                    System.arraycopy(flashBuff, (int)dwStartAddrPos, bufRead, 6, dwDataLen);

                    recvLen = SendRecvCmd(0x1F13,bufRead, recvBuff,10*1000);
                    if (recvLen < 0)
                    {
                        Log.i(TAG,"错误：对flash进行编程");
                        isFailed = true;
                        break;
                    }

                    strTemp = String.format("09-%03d/%d,",i,dwSize/256);
                    //Log.i(TAG,strTemp + "成功：对flash进行编程");
                    mHandler.sendMessage(new CommEvent(
                            CommDefine.MESSAGE_UPGRAD,
                            CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());
                }

            if(isFailed){
                return 1;
            }
            Log.i(TAG,"成功：对flash进行编程");
            // 0x1F0C 进入应用程序
            recvLen = SendRecvCmd(0x1F0C, new byte[0], recvBuff);
//			if(recvLen < 0 ){
//				Log.i(TAG,"12,错误：进入应用程序");
//				return 1;
//			}
//			Log.i(TAG,"12,成功：进入应用程序");


            mHandler.sendMessage(new CommEvent(
                    CommDefine.MESSAGE_UPGRAD,
                    CommDefine.MESSAGE_UPGRAD_UPDATEING,currProgress++).getMsg());

            return 0;
        }

        /**
         * 运行在ui线程中，在doInBackground()执行完毕后执行
         */
        @Override
        protected void onPostExecute(Integer integer) {
            switch (integer) {
                case 0:
                    mHandler.sendMessage(new CommEvent(
                            CommDefine.MESSAGE_UPGRAD,
                            CommDefine.MESSAGE_UPGRAD_SUCCESS).getMsg());
//                   stop();
//                    mCurrVer = mNewVer;
//                    mtvCurrVer.setText(mCurrVer);
//                    final VDialog dlgSuccess = DialogUtils.showAlartOk(
//                            UpgradActivity.this,"升级完成",
//                            getResources().getString(
//                                    R.string.upgrad_model_success));
//
//                    dlgSuccess.setOnDismissListener(new OnDismissListener() {
//
//                        @Override
//                        public void onDismiss(DialogInterface dialog) {
//                            // TODO Auto-generated method stub
//                            MainActivity.WakeLockRelease(UpgradActivity.this,false);
//                            EventBus.getDefault().post(new AppEvent(CommDefine.MESSAGE_APP,CommDefine.MESSAGE_APP_EXIT_WITH_SERVICE));
//                            //EventBus.getDefault().post(new AppEvent(CommDefine.MESSAGE_APP, CommDefine.MESSAGE_APP_UPGRAD_END));
//                            //EventBus.getDefault().post(new AppEvent(CommDefine.MESSAGE_APP, CommDefine.MESSAGE_APP_UPGRAD_START));
//                            finish();
//                        }
//
//                    });
//                    dlgSuccess.show();

                    break;
                case 1:
                    CommDefine.addLog(TAG,"升级失败");

                    mHandler.sendMessage(new CommEvent(
                            CommDefine.MESSAGE_UPGRAD,
                            CommDefine.MESSAGE_UPGRAD_FAILURE).getMsg());
//                    stop();
//                    mbtnUpgrad.setText("升级失败");
//                    mbtnUpgrad.setBackgroundColor(Color.RED);
//                    final VDialog dlgFail = DialogUtils.showAlart(
//                            UpgradActivity.this,"升级失败",
//                            getResources().getString(
//                                    R.string.upgrad_model_tip),
//                            getResources().getString(
//                                    R.string.btn_cancel),
//                            getResources().getString(
//                                    R.string.btn_retry));
//
//                    dlgFail.setOnDismissListener(new OnDismissListener() {
//
//                        @Override
//                        public void onDismiss(DialogInterface dialog) {
//                            // TODO Auto-generated method stub
//                            if(dlgFail.getResult() == VDialog.RESULT_OK){
//                                EventBus.getDefault().post(new AppEvent(CommDefine.MESSAGE_APP, CommDefine.MESSAGE_APP_UPGRAD_START));
//                                UpgradTask upgradTask = new UpgradTask(UpgradActivity.this);
//                                upgradTask.execute();
//                            }else{
//                                MainActivity.WakeLockRelease(UpgradActivity.this,false);
//                                EventBus.getDefault().post(new AppEvent(CommDefine.MESSAGE_APP,CommDefine.MESSAGE_APP_EXIT_WITH_SERVICE));
//                                finish();
//                            }
//                        }
//
//                    });
//                    dlgFail.show();
                    break;
            }
 //           mbtnUpgrad.setProgress(maxProgress);
        }

        /**
         * 在publishProgress()被调用以后执行，publishProgress()用于更新进度
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
        }
    }
}
